package com.xinxing.learning.datasource.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xinxing.learning.datasource.constants.ConfigConstant;
import com.xinxing.learning.datasource.context.SpringContextUtils;
import com.xinxing.learning.datasource.mapper.DatasourceMapper;
import com.xinxing.learning.datasource.model.DynamicDataSourceModel;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class DataSourceCachePool {
    private static Map<String, DruidDataSource> dbSources = new HashMap<>();
    private volatile static RedisTemplate<String, Object> redisTemplate;

    private static RedisTemplate<String, Object> getRedisTemplate() {
        if (redisTemplate == null) {
            synchronized (dbSources) {
                if (redisTemplate == null) {
                    redisTemplate = (RedisTemplate<String, Object>) SpringContextUtils.getBean("redisTemplate");
                }
            }
        }
        return redisTemplate;
    }

    public static DynamicDataSourceModel getCacheDynamicDataSourceModel(String dbKey) {
        String redisCacheKey = ConfigConstant.SYS_DYNAMIC_DB_CACHE + dbKey;
        if (getRedisTemplate().hasKey(redisCacheKey)) {
            return JSON.parseObject(getRedisTemplate().opsForValue().get(redisCacheKey).toString(), DynamicDataSourceModel.class);
        }
        DatasourceMapper datasourceMapper = (DatasourceMapper) SpringContextUtils.getBean("datasourceMapper");
        DynamicDataSourceModel dataSource = datasourceMapper.getDynamicDbSourceByCode(dbKey);
        if (Objects.nonNull(dataSource)) {
            getRedisTemplate().opsForValue().set(redisCacheKey, JSONObject.toJSONString(dataSource));
        }
        return dataSource;
    }

    public static DruidDataSource getCacheBasicDataSource(String dbKey) {
        return dbSources.get(dbKey);
    }

    public static void putCacheBasicDataSource(String dbKey, DruidDataSource dataSource) {
        dbSources.put(dbKey, dataSource);
    }

    public static void cleanAllCache() {
        for (Map.Entry<String, DruidDataSource> entry : dbSources.entrySet()) {
            String dbKey = entry.getKey();
            DruidDataSource druidDataSource = entry.getValue();
            if (Objects.nonNull(druidDataSource) && druidDataSource.isEnable()) {
                druidDataSource.close();
            }
            getRedisTemplate().delete(ConfigConstant.SYS_DYNAMIC_DB_CACHE + dbKey);
        }

        dbSources.clear();
    }

    public static void removeCache(String dbKey) {
        DruidDataSource druidDataSource = dbSources.get(dbKey);
        if (Objects.nonNull(druidDataSource) && druidDataSource.isEnable()) {
            druidDataSource.close();
        }

        getRedisTemplate().delete(ConfigConstant.SYS_DYNAMIC_DB_CACHE + dbKey);

        dbSources.remove(dbKey);
    }
}
